package com.ziki.account.service;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.ziki.account.api.v1.request.SendCodeRequest;
import com.ziki.account.component.SmsComponent;
import com.ziki.account.service.strategy.MapSendStrategyFactory;
import com.ziki.account.service.strategy.VerifyStrategy;
import com.ziki.common.constant.CacheConstants;
import com.ziki.common.enums.SendCodeType;
import com.ziki.common.util.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author tianyi
 * @since 2023-02-23 17:10
 */
@Service
@Slf4j
public class NotifyService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private SmsComponent smsComponent;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    @Qualifier("captchaProducerString")
    private DefaultKaptcha defaultKaptcha;

    /**
     * @Async失效情况： TODO 异步发送方案OOM问题
     */
    @Async("threadPoolTaskExecutor")
    public void testSend(String site) {
        ///notify/v1/send-code?name=http://47.98.233.38:5212/login
        if (StrUtil.isBlank(site)) {
            site = "https://www.xdclass.net/";
        }

        // 发送验证码模拟
        // 方案1
//        try {
//            TimeUnit.MICROSECONDS.sleep(400);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
        // 方案2
        ResponseEntity<String> forEntity = this.restTemplate.getForEntity(site, String.class);
        String body = forEntity.getBody();
        log.info(body);
    }

    public void send(SendCodeRequest sendCodeRequest) {
        // 发送业务验证码
        VerifyStrategy verifyStrategy = MapSendStrategyFactory.getChargeStrategy(sendCodeRequest.getType());
        verifyStrategy.send(sendCodeRequest.getTo(), sendCodeRequest.getType().name());
    }

    public Map<String, Object> getCaptcha() {
        // 生成图形验证码
        String captcha = this.defaultKaptcha.createText();
        BufferedImage captchaImage = this.defaultKaptcha.createImage(captcha);
        // 存入redis并设置过期时间
        String captchaId = IdUtil.getSnowflakeNextIdStr();
        String captchaKey = CacheConstants.CAPTCHA_CODE_KEY + captchaId;
        log.info("captchaId:[{}],captcha:[{}]", captchaId, captcha);
        this.redisCache.setCacheObject(captchaKey, captcha, CacheConstants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        // 转换流信息写出
        try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
            ImgUtil.write(captchaImage, ImgUtil.IMAGE_TYPE_JPG, os);
            Map<String, Object> map = new HashMap<>();
            map.put("img", Base64.encodeBase64String(os.toByteArray()));
            map.put("captcha_id", captchaId);
            return map;
        }
    }

    @Deprecated
    public Map<String, Object> getCaptcha(ServletResponse response) {
        // 生成图形验证码
        String captcha = this.defaultKaptcha.createText();
        BufferedImage captchaImage = this.defaultKaptcha.createImage(captcha);
        // 存入redis并设置过期时间
        String captchaId = IdUtil.getSnowflakeNextIdStr();
        String captchaKey = CacheConstants.CAPTCHA_CODE_KEY + captchaId;

        log.info("captchaId:[{}],captcha:[{}]", captchaId, captcha);

        this.redisCache.setCacheObject(captchaKey, captcha, CacheConstants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // 转换流信息写出
        try {
            ImgUtil.write(captchaImage, ImgUtil.IMAGE_TYPE_JPG, response.getOutputStream());
        } catch (IOException e) {
            log.error("验证码写出异常", e);
        }
        return null;
    }

    public boolean verify(SendCodeType type, String to, String code) {
        // key account-services:code:register:to
        String codeKey = String.format(CacheConstants.CHECK_CODE_KEY, type.name(), to);
        // value code_timestamp
        String codeCache = this.redisCache.getCacheObject(codeKey);
        log.info("get redis [{}]", codeCache);
        if (StringUtils.hasText(codeCache)) {
            String value = codeCache.split("_")[0];
            // 验证码匹配
            if (code.equalsIgnoreCase(value)) {
                this.redisCache.deleteObject(codeKey);
                return true;
            }
        }
        return false;
    }
}
